import glob
import imghdr
import json
import os
import platform
import random
import re
import shutil

import arrow
import httpx
import qrcode

from pathlib import Path

from io import BytesIO
from PIL import Image, ImageDraw, ImageFont

from config.config import *


def openid(code):
    """
    获取OPENID
    """

    params = {
        "appid": WX_APPID,
        "secret": WX_SECRET,
        "js_code": code,
        "grant_type": "authorization_code",
    }

    openid = None

    try:
        r = httpx.get("https://api.weixin.qq.com/sns/jscode2session", params=params)

        if r.status_code == 200:
            openid = r.json().get("openid")
    except BaseException:
        pass

    return openid


def upload_to_oss(filename, contents, mock=False):
    """
    上传文件到OSS
    """

    def upload_to_aliyun(filename, contents, mock=False):
        import oss2

        auth = oss2.Auth(ALIYUN_ACCESS_KEY_ID, ALIYUN_ACCESS_KEY_SECRET)
        bucket = oss2.Bucket(auth, ALIYUN_END_POINT, ALIYUN_BUCKET_NAME)
        oss_path = f"https://{ALIYUN_OSS_NAME}"

        key = Path("media").joinpath(filename).as_posix()

        try:
            if not mock:
                bucket.put_object(key, contents)

            return "/".join((oss_path, key))
        except BaseException:
            return None

    if not mock and imghdr.what(BytesIO(contents)):
        image = Image.open(BytesIO(contents))

        ios = BytesIO()
        image.save(ios, "webp")
        ios.seek(0)
        contents = ios.read()

        filename = Path(filename).with_suffix(".webp").as_posix()

    return upload_to_aliyun(filename, contents, mock)


def send_message(phone, template_code, template_param):
    """
    发送短信
    """

    from aliyunsdkcore.client import AcsClient
    from aliyunsdkcore.request import CommonRequest

    access_key_id = ALIYUN_ACCESS_KEY_ID
    access_secret = ALIYUN_ACCESS_KEY_SECRET
    sign_name = ALIYUN_SIGN_NAME

    client = AcsClient(access_key_id, access_secret, "cn-hangzhou")

    request = CommonRequest()
    request.set_domain("dysmsapi.aliyuncs.com")
    request.set_method("POST")
    request.set_protocol_type("https")
    request.set_version("2017-05-25")
    request.set_action_name("SendSms")

    request.add_query_param("RegionId", "cn-hangzhou")
    request.add_query_param("PhoneNumbers", phone)
    request.add_query_param("SignName", sign_name)
    request.add_query_param("TemplateCode", template_code)
    request.add_query_param("TemplateParam", json.dumps(template_param))

    try:
        response = json.loads(client.do_action_with_exception(request))

        if response.get("Code") != "OK":
            response = None
    except BaseException:
        pass

    return response


def push_notification(devid, message, data=None):
    """
    发送APP通知
    """

    import jpush

    push = jpush.JPush(JPUSH_KEY, JPUSH_SECRET).create_push()
    push.platform = ["android"]
    push.audience = jpush.registration_id(devid)

    android = jpush.android(alert=message, priority=2, extras=data)

    push.notification = jpush.notification(android=android)

    response = None

    try:
        response = push.send()
    except BaseException:
        pass

    return response


def localtime(time):
    """
    获取本地时间
    """

    return arrow.get(time).to("Asia/Shanghai")


def localtime_day(time):
    """
    获取本地日期开始时间
    """

    return localtime(time).replace(hour=0, minute=0, second=0, microsecond=0)


def add_image_mark(image, resize=False):
    """
    给图片增加日期水印
    """

    image = image.convert("RGB")

    mark = localtime(arrow.utcnow()).format("YYYY-MM-DD HH:mm:ss")
    draw = ImageDraw.Draw(image)

    width, height = image.size
    font = ImageFont.truetype(
        get_system_font(("STHeiti Medium", "wqy-microhei")),
        int(max(min(width, height) / 25, 10)),
    )

    mark_width, mark_height = draw.textsize(mark, font)
    margin = mark_height

    draw.text(
        (width - mark_width - margin, height - mark_height - margin), mark, "red", font
    )

    if resize:
        mark_width = min(image.width, 1024)
        mark_height = int(image.height * (mark_width / image.width))

        image = image.resize((mark_width, mark_height))

    return image


def get_system_font(default_fonts=None):
    """
    获取系统字体名称
    """

    dirs = []

    if platform.system().lower() == "win32":
        dirs.append(Path(os.environ.get("WINDIR")).joinpath("fonts").as_posix())
    elif platform.system().lower() == "linux":
        for path in os.environ.get("XDG_DATA_DIRS", "/usr/share").split(":"):
            dirs.append(Path(path).joinpath("fonts").as_posix())
    elif platform.system().lower() == "darwin":
        dirs.append("/Library/Fonts")
        dirs.append("/System/Library/Fonts")
        dirs.append(Path("~/Library/Fonts").expanduser().as_posix())
    else:
        pass

    map = {}

    for dir in dirs:
        for filename in glob.iglob(
            Path(dir).joinpath("**/*").as_posix(), recursive=True
        ):
            file = Path(filename)

            if file.suffix in (".ttf", ".ttc"):
                name = Path(filename).name
                map[name[:-4]] = f"{name[-3:]}_{name}"

    font = None

    if map:
        font = sorted(map.keys(), key=lambda k: map.get(k))[0]

    if default_fonts:
        for name in default_fonts:
            if name in map:
                font = name

                break

    return font


def boolean_string(string, default=False):
    """
    转换BOOL字符串
    """

    if not str(string or ""):
        return default

    return str(string).lower() == "true"


def make_qrcode(string, filename=None):
    import qrcode

    image = qrcode.make(string)

    if filename:
        stream = BytesIO()
        image.save(stream, format="png")

        filename = upload_to_oss(filename, stream.getvalue())

        return filename
    else:
        return image


def fix_filename(name):
    return re.sub(r'[\\/:*?"<>|\s]+', "", name)


def get_urlfilename(request, filename):
    """
    获取URL文件名
    """

    origin = request.headers.get("origin") or request.headers.get("referer") or ""

    if origin.startswith("http://"):
        type = "http"
    else:
        type = "https"

    return f'{type}://{request.headers.get("host")}/{filename}'


def get_tmpdir(mkdir=False):
    """
    获取临时目录
    """

    tmpdir = Path(BASE_DIR).joinpath("media/tmpdir", arrow.utcnow().format("YYYYMMDD"))

    if mkdir:
        tmpdir.mkdir(parents=True, exist_ok=True)

    return tmpdir.as_posix()


def get_tmpfilename():
    """
    获取临时文件名
    """

    return f"{arrow.utcnow().format('YYYYMMDDHHmmss')}_{random.randint(1000, 9999)}"


def clean_tmpdir():
    """
    清除临时目录
    """

    tmpdir = Path(BASE_DIR).joinpath("media/tmpdir")
    ignore_dir = arrow.utcnow().format("YYYYMMDD")

    for filename in glob.iglob(tmpdir.joinpath("*").as_posix()):
        path = Path(filename)

        if path.name == ignore_dir:
            continue

        shutil.rmtree(path.as_posix(), ignore_errors=True)
